package ihm;

import image.FormDetector2;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.smartcardio.CardException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;

import security.AES256;

import application.LeGroupe4;
import application.smartcard.SmartCard;
import application.smartcard.SmartCardManager;
import database.bean.AuthCardData;
import database.bean.User;
import database.hibernate.HibernateUtil;

public class AuthentificationFrame2 extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JPasswordField passwordField;
	public boolean videoON = true;
	final static VideoPanel2 videoPanel = new VideoPanel2();

	private static final String STATUS_PHOTO = "Veuillez prendre une photo pour vous identifier";
	private static final String STATUS_PHOTO_CARD = "Retirer la card et reprenez une photo";
	private static final String STATUS_BIO_SUCCEED = "Veuillez inserer votre carte d'acces";
	private static final String STATUS_BIO_IN_PROGRESS = "Analyse biometrique en cours";
	private static final String STATUS_CARD_FAILED = "Carte non correspondante";
	private static final String STATUS_CARD_SUCCEED = "Inserez votre mot de passe";
	private static final String STATUS_MDP_FAILED = "Mot de passe errone, veuillez resaisir";
	private static final String STATUS_MDP_SUCCEED = "Authentification reussie : retirer la carte"; 
	
	private static final String BUTTON_PHOTO = "Prendre une photo";
	private static final String BUTTON_VIDEO = "Relancer la video";
	
	
	
	private JButton button;
	private JLabel statut_lbl;
	private JLabel name_lbl;
	private JLabel iDcard_lbl;

	private Mat snapshot = null;
	
	/**
	 * Launch the application.
	 */

	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					AuthentificationFrame2 frame = new AuthentificationFrame2();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public AuthentificationFrame2() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 680, 650);
		setTitle("Authentification");
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);

		contentPane.add(videoPanel, BorderLayout.CENTER);

		JPanel panel = new JPanel();
		contentPane.add(panel, BorderLayout.SOUTH);
		panel.setLayout(new GridLayout(1, 1, 0, 0));

		JPanel panel_1 = new JPanel();
		panel.add(panel_1);
		panel_1.setLayout(new GridLayout(0, 2, 0, 0));

		button = new JButton(STATUS_PHOTO);
		panel_1.add(button);

		JPanel panel_3 = new JPanel();
		panel_3.setBackground(Color.WHITE);
		panel_1.add(panel_3);
		panel_3.setLayout(new GridLayout(4, 1, 0, 0));

		statut_lbl = new JLabel("Statut :");
		statut_lbl.setBackground(Color.WHITE);
		panel_3.add(statut_lbl);

		name_lbl = new JLabel("Name : ");
		name_lbl.setBackground(Color.WHITE);
		name_lbl.setVisible(false);
		panel_3.add(name_lbl);

		iDcard_lbl = new JLabel("ID card :");
		iDcard_lbl.setBackground(Color.WHITE);
		iDcard_lbl.setVisible(false);
		panel_3.add(iDcard_lbl);

		JPanel panel_4 = new JPanel();
		panel_4.setBackground(Color.WHITE);
		panel_3.add(panel_4);
		GridBagLayout gbl_panel_4 = new GridBagLayout();
		gbl_panel_4.columnWidths = new int[] { 81, 6, 89, 0 };
		gbl_panel_4.rowHeights = new int[] { 23, 0 };
		gbl_panel_4.columnWeights = new double[] { 1.0, 0.0, 0.0,
				Double.MIN_VALUE };
		gbl_panel_4.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
		panel_4.setLayout(gbl_panel_4);

		passwordField = new JPasswordField();
		passwordField.setEditable(false);
		GridBagConstraints gbc_passwordField = new GridBagConstraints();
		gbc_passwordField.fill = GridBagConstraints.BOTH;
		gbc_passwordField.gridwidth = 2;
		gbc_passwordField.insets = new Insets(0, 0, 0, 5);
		gbc_passwordField.gridx = 0;
		gbc_passwordField.gridy = 0;
		panel_4.add(passwordField, gbc_passwordField);

		JButton ok = new JButton("ok");
		GridBagConstraints gbc_ok = new GridBagConstraints();
		gbc_ok.fill = GridBagConstraints.HORIZONTAL;
		gbc_ok.anchor = GridBagConstraints.NORTH;
		gbc_ok.gridx = 2;
		gbc_ok.gridy = 0;
		panel_4.add(ok, gbc_ok);

		// action Listener
		button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println("je clique");
				if (videoON) {
					// take picture
					videoON = false;
					snapshot = videoPanel.capture();
					videoPanel.stop();
					button.setText(BUTTON_VIDEO);
					statut_lbl.setText(STATUS_BIO_IN_PROGRESS);
					// TODO appel de la fonction biom?trique
					//statut_lbl.setText(STATUS_BIO_IN_PROGRESS);
					
					// TODO appel de la fonction biometrique
					Mat untouched = snapshot.clone();
					Mat draw = snapshot.clone();
					
					/*FormDetector2 fd = new FormDetector2();
					Point[] eye_zone = FormDetector2.findFace(snapshot, "", draw);
					Point[] eye = FormDetector2.findEye(snapshot, eye_zone, "", draw);*/
					//Point[] eye = FormDetector2.irisRecognitionLD(snapshot, draw, "");
					Point[] eye = FormDetector2.irisRecognitionHD(snapshot, draw, "");
					String histo1 = FormDetector2.computeHisto(untouched, eye);
					
					// affiche le resultat a l'ecran
					videoPanel.AfficherImage(draw);
					
					//System.out.println("exit dans AuthentificationFrame2 pour les tests sans lecteur de carte");
					
					// on récupère les utilisateurs
					Session session = HibernateUtil.getSession();
					Transaction tx = session.beginTransaction();

					// variables pour accéder au keyStore
					final String ksPath = "C:\\Users\\B182JS\\workspace\\projet_SmartCard\\bin\\aesKeyStore.keystore";
					final char[] ksPassword = {'t','o','t','o'};
					final char[] keyPassword = {'t','o','t','o'};
					String alias = "aesKey";
					
					SecretKey aesKey = AES256.loadKeyFromKeyStore(ksPath, ksPassword, keyPassword, alias);
					
					Cipher encryptCipher = null;
					try {
						encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
						encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
					} catch (NoSuchAlgorithmException e) {
						e.printStackTrace();
					} catch (NoSuchPaddingException e) {
						e.printStackTrace();
					} catch (InvalidKeyException e) {
						e.printStackTrace();
					}
					
					List<User> users = session.createCriteria(User.class).list();
					byte[] encrypted_bio = null;
					byte[] decrypted_bio = null;
					User matched = null;
					double min = Double.MAX_VALUE;
					double dist = 0;
					
					for(User u : users) {
						if(u.getUser_biometric_data() != null) {
							encrypted_bio = u.getUser_biometric_data();
							decrypted_bio = AES256.decrypt(encrypted_bio, aesKey, encryptCipher);

							dist = FormDetector2.compareHistoEuclid(histo1, new String(decrypted_bio));
							if(dist < min) {
								min = dist;
								matched = u;
							}
							System.out.println(u.getUser_name()+"\tEuclid\t"+dist);
							//System.out.println(u.getUser_name()+"\tBata\t"+FormDetector2.compareHistoBata(histo1, new String(decrypted_bio)));
						}
					}
					
					System.out.println("reconnu "+matched.getUser_name());
					
					//TODO comparer le résultat avec la BDD
					String biometricUID = String.valueOf(matched.getCard().getCard_uid());
					LeGroupe4.setBiometricUID(biometricUID);
					//TODO décommenter la ligne du dessus
					
					System.out.println("draw finish");
					
					// operation reussie
					managementStatut(01);
					
					//TODO Traitement ici ou déplacé dans LeGroupe4!
					tx.commit();
					LeGroupe4.setWaitForCard();
					
					System.out.println("authentification terminee!");
					
				} else {
					button.setText(BUTTON_PHOTO);
					managementStatut(07);
					videoON = true;
					
					videoPanel.play();
				}
			}
		});

		ok.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// derniere etape : verification du mdp !
				LeGroupe4.setWaitForPasswordControl();
			}
		});
		
		this.setVisible(true);
		videoPanel.play();
	}

	public void managementStatut(int statusCode) {
		switch (statusCode) {
		case 01:
			//biosuccess
			statut_lbl.setText(STATUS_BIO_SUCCEED);
			name_lbl.setVisible(true);
			button.setEnabled(false);
			break;
		case 02:
			//bioFailed
			statut_lbl.setText(STATUS_PHOTO);
			
			break;
		case 03:
			statut_lbl.setText(STATUS_CARD_SUCCEED);
			passwordField.setEditable(true);
			break;
		case 04:
			statut_lbl.setText(STATUS_CARD_FAILED);
			break;
		case 05:
			statut_lbl.setText(STATUS_MDP_FAILED);
			break;
		case 06:
			statut_lbl.setText(STATUS_MDP_SUCCEED);
			button.setEnabled(true);
			break;
		case 07:
			statut_lbl.setText(STATUS_PHOTO_CARD);
			button.setEnabled(true);
			updateLabelVisible(getiDcardLabel(), false);
			updateLabelText(getiDcardLabel(), "");
			updateLabelVisible(getNameLabel(), true);
			updateLabelText(getNameLabel(), "");
			passwordField.setVisible(false);
			passwordField.setEditable(false);
			break;
		default:

		}
	}

	/**
	 * modifie le texte du label
	 * @param label le label ? modifier
	 * @param text le nouveau texte du label
	 */
	public void updateLabelText(JLabel label, String text){
		label.setText(text);
	}

	/**
	 * permet d'autoriser ou interdire l'?dition d'un champ texte
	 * @param tf champ texte ou mot de passe
	 * @param b  'true' : autorise l'?dition, 'false' interdit l'?dition
	 */
	public void updateFieldEdition(JTextField tf, boolean b){
		tf.setEditable(b);
	}

	public void updateFieldText(JTextField tf, String text){
		tf.setText(text);
	}
	
	public void updatePasswordText(JPasswordField pf, String text){
		pf.setText(text);
	}
	
	public void updateLabelVisible(JLabel jl, boolean b){
		jl.setVisible(b);
	}
	
	public void updatePasswordVisible(JPasswordField pf, boolean b){
		pf.setVisible(b);
	}

	public JPasswordField getPasswordField() {
		return passwordField;
	}

	public JLabel getStatutLabel() {
		return statut_lbl;
	}

	public JLabel getNameLabel() {
		return name_lbl;
	}

	public JLabel getiDcardLabel() {
		return iDcard_lbl;
	}
	
	
}
